<?php
namespace Game\Action\Character;

use Game\Action\AbstractAction;
use Game\Entity\Character as EntityCharacter;

class PunchAction extends AbstractAction
{
    private $_miss;
    private $_damage;
    private $_opponent = array();
    private $_kill;

    public function getCode()
    {
        return 'punch';
    }

    public function getDescription()
    {
        return 'Уебать с руки';
    }

    public function execute($character)
    {
        $character instanceof EntityCharacter;
        $msg = '';

        $this->_opponent['id'] = $character->getId();
        $this->_opponent['name'] = $character->getName();
        if( $this->_isHit($character) )
        {
            $this->_miss = false;
            $damage = $this->_calculateDamage($character);
            $character->makeDamage($damage);
            $this->_damage = $damage;
            if( $character->isAlive() )
            {
                $this->_kill = false;
                $this->_opponent['hp'] = $character->getHp();
                $msg = sprintf('%1$s punchs %2$s with %3$d damage, %2$s has %4$d hp',
                    $this->getOwner(),
                    $character,
                    $damage,
                    $character->getHp()
                );
            }
            else
            {
                $this->_kill = true;
                $this->_opponent['hp'] = 0;
                $msg = sprintf('%1$s punchs %2$s with %3$d damage, %2$s is dead',
                    $this->getOwner(),
                    $character,
                    $damage
                );
            }

        }
        else
        {
            $this->_miss = true;
            $this->_kill = false;
            $this->_damage = 0;
            $this->_opponent['hp'] = $character->getHp();
            $msg = sprintf('%s is missed', $this->getOwner());
        }
        $this->_message = $msg;
        return $msg;
    }

    /**
     *
     * @return integer
     */
    protected function _getOwnerMaxDamage()
    {
        return $this->getOwner()->getBaseDamage() + $this->getOwner()->getPower();
    }

    /**
     *
     * @param integer $max_damage
     * @return integer
     */
    protected function _getOwnerMinDamage($max_damage = 0)
    {
        if( !$max_damage ) $max_damage = $this->_getOwnerMaxDamage();
        $min1 = $max_damage - 1;
        $min2 = $this->getOwner()->getBaseDamage() + $this->getOwner()->getAgility();
        return ($min2 < $min1? $min2 : $min1);
    }

    /**
     *
     * @return integer
     */
    protected function _getOwnerDamage()
    {
        $min = $this->_getOwnerMinDamage();
        $max = $this->_getOwnerMaxDamage();
        return mt_rand($min, $max);
    }

    /**
     * Calculate damage value
     * @param EntityCharacter $character
     * @return integer
     */
    protected function _calculateDamage(EntityCharacter $character)
    {
        $owner_damage = $this->_getOwnerDamage();

        $damage = $owner_damage;
        return $damage;
    }

    /**
     * Checks whether owner hits character or not
     * @param EntityCharacter $character
     * @return boolen
     */
    protected function _isHit(EntityCharacter $character)
    {
        $luck_coeff = 0.25;
        $owner = $this->getOwner();
        $owner instanceof EntityCharacter;
        $owner_sum = $owner->getAccuracy() + $owner->getLuck() * $luck_coeff;
        $char_sum = $character->getAccuracy() + $character->getLuck() * $luck_coeff;
        $sum = $owner_sum + $char_sum;
        $hit_prob = round($owner_sum/$sum, 3) * 1000;
        $rnd = mt_rand(0, 1000);
        return $rnd <= $hit_prob;
    }

    public function getResultArray()
    {
       return $array = array(
            'message' => $this->getMessage(),
            'miss' => $this->_miss,
            'damage' => $this->_damage,
            'opponent' => $this->_opponent,
            'kill' => $this->_kill,
        );
    }
}